package com.flyqiu.form.store.mysql;


import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.flyqiu.common.bean.FlyQiuBeanManage;
import com.flyqiu.common.core.UUIdTools;
import com.flyqiu.common.mybaits.plus.FlyQiuQueryWrapper;
import com.flyqiu.common.tools.FlyQiuCollectionTools;
import com.flyqiu.form.api.FlyQiuFormContext;
import com.flyqiu.form.api.store.FlyQiuBaseFormStorageService;
import com.flyqiu.form.common.FlyQiuFormConstant;
import com.flyqiu.form.common.exceptions.FlyQiuFormException;
import com.flyqiu.form.model.FlyQiuColumnInfo;
import com.flyqiu.form.model.FlyQiuFormData;
import com.flyqiu.form.model.SqlColumnModel;
import com.flyqiu.form.model.entity.FlyQiuTableConfig;
import com.flyqiu.form.model.vo.SqlColumnVo;
import com.flyqiu.form.store.mysql.mapper.FlyQiuFormMySqlStoreMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 数据库存储器
 */
@Component(FlyQiuFormMySqlStore.STORAGE_KEY)
public class FlyQiuFormMySqlStore extends FlyQiuBaseFormStorageService {

    public static final String STORAGE_KEY = "flyQiuFormMySqlStorage";

    private final FlyQiuFormMySqlStoreMapper storageMapper;

    public FlyQiuFormMySqlStore(FlyQiuFormContext formContext) {
        super(formContext);
        FlyQiuBeanManage beanManage = formContext.getBeanManage();
        storageMapper = beanManage.getMapper(FlyQiuFormMySqlStoreMapper.class);
    }


    /**
     * 获取当前存储器唯一标识 一般默认当前bean 名称
     *
     * @return
     */
    @Override
    public String getStorageKey() {
        return STORAGE_KEY;
    }

    /**
     * 获取当前存储器名称
     *
     * @return
     */
    @Override
    public String getStorageLabel() {
        return "mysql数据库存储器";
    }


    @Override
    public Page storagePage(FlyQiuTableConfig config, Page page, List<SqlColumnModel> column, FlyQiuQueryWrapper query) {
        Page storage = storageMapper.pageStorage(page, config.getTableName(), column, query);
        List records = storage.getRecords();
        storage.setRecords(null);
        List<JSONObject> list = listMapToJSON(records);
        storage.setRecords(list);
        return storage;
    }

    private List<JSONObject> listMapToJSON(List rows) {
        List<JSONObject> list = new ArrayList<>(rows.size());
        if (rows.isEmpty()) return list;
        for (Object row : rows) {
            list.add(JSONObject.from(row));
        }
        return list;
    }

    @Override
    public List<JSONObject> storageList(FlyQiuTableConfig config, List<SqlColumnModel> column, FlyQiuQueryWrapper query) {
        String tableName = config.getTableName();
        List<Map<String, Object>> maps = storageMapper.storageList(tableName, column, query);
        return listMapToJSON(maps);
    }


    @Override
    public List<SqlColumnModel> getStorageColumnConfig(FlyQiuTableConfig formConfig) {
        return storageMapper.getTableColumns(formConfig.getTableName());
    }

    @Override
    public String storageSave(FlyQiuTableConfig config, List<SqlColumnModel> columns, JSONObject data) {
        List<SqlColumnModel> tableColumns = storageMapper.getTableColumns(config.getTableName());
        String id = UUIdTools.createId32();
        if (data.containsKey(FlyQiuFormConstant.FormBaseColumns.COLUMN_PK_NAME)) {
            data.replace(FlyQiuFormConstant.FormBaseColumns.COLUMN_PK_NAME, id);
        } else {
            data.put(FlyQiuFormConstant.FormBaseColumns.COLUMN_PK_NAME, id);
        }
        List<FlyQiuFormData> formDatas = new ArrayList<>();
        for (SqlColumnModel column : tableColumns) {
            if (!data.containsKey(column.getProp())) continue;
            FlyQiuFormData formData = new FlyQiuFormData();
            formData.setDataValue(data.getString(column.getProp()));
            formData.setProp(column.getProp());
            formDatas.add(formData);
        }
        storageMapper.storageSave(config.getTableName(), formDatas);
        return id;
    }


    @Override
    public Long storageUpdate(FlyQiuTableConfig config, List<SqlColumnModel> columns, JSONObject data, FlyQiuQueryWrapper queryWrapper) {
        List<SqlColumnModel> tableColumns = storageMapper.getTableColumns(config.getTableName());
        List<FlyQiuFormData> formDatas = new ArrayList<>();
        for (SqlColumnModel column : tableColumns) {
            if (!data.containsKey(column.getProp())) continue;
            if (column.getProp().equals(FlyQiuFormConstant.FormBaseColumns.COLUMN_PK_NAME)) continue;
            FlyQiuFormData formData = new FlyQiuFormData();
            formData.setDataValue(data.getString(column.getProp()));
            formData.setProp(column.getProp());
            formDatas.add(formData);
        }
        return storageMapper.storageUpdate(config.getTableName(), formDatas, queryWrapper);
    }

    /**
     * 删除数据
     *
     * @param config       数据表配置
     * @param queryWrapper 条件
     * @return long 影响行数量
     */
    @Override
    protected long storageRemove(FlyQiuTableConfig config, FlyQiuQueryWrapper queryWrapper) {
        if (StringUtils.isEmpty(queryWrapper.getCustomSqlSegment())) {
            throw new FlyQiuFormException("系统禁止删除全部数据");
        }
        Long num = storageMapper.storageRemove(config.getTableName(), queryWrapper);
        if (num == null) {
            return 0;
        }
        return num;
    }

    /**
     * 查询数据数量
     *
     * @param config       数据表配置
     * @param queryWrapper 查询条件
     * @return long 数据总数
     */
    @Override
    protected long storageCount(FlyQiuTableConfig config, FlyQiuQueryWrapper queryWrapper) {
        return storageMapper.storageCount(config.getTableName(), queryWrapper);
    }


    @Override
    public List<SqlColumnModel> storageSynchronizationTable(FlyQiuTableConfig formConfig, FlyQiuColumnInfo flyQiuColumnInfo) {
        Map<String, String> table = storageMapper.getTableByTableName(formConfig.getTableName());
        if (table == null || table.isEmpty()) {
            return createSQLTable(formConfig, flyQiuColumnInfo);
        }
        return updateTable(table, formConfig, flyQiuColumnInfo);
    }


    /**
     * 修改数据表
     *
     * @param oldTableInfo     旧表信息
     * @param formConfig       新表信息
     * @param flyQiuColumnInfo 列信息
     * @return List<SqlColumnModel> 列信息
     */
    private List<SqlColumnModel> updateTable(Map<String, String> oldTableInfo, FlyQiuTableConfig formConfig, FlyQiuColumnInfo flyQiuColumnInfo) {
        if (!oldTableInfo.containsKey("table_comment") || oldTableInfo.getOrDefault("table_comment", "").equals(formConfig.getFormName())) {
            storageMapper.updateTableComment(formConfig);
        }
        List<SqlColumnModel> columns = new ArrayList<>();
        columns.addAll(flyQiuColumnInfo.getAddLists());
        columns.addAll(flyQiuColumnInfo.getEditColumns());
        columns.forEach(e -> e.setId(e.getProp()));
        deleteColumns(formConfig.getTableName(), flyQiuColumnInfo.getDeleteColumns());
        updateColumns(formConfig.getTableName(), flyQiuColumnInfo.getEditColumns());
        addColumns(formConfig.getTableName(), flyQiuColumnInfo.getAddLists());
        synchronizeColumn(formConfig, columns);
        return columns;
    }

    /**
     * 创建数据表
     *
     * @param formConfig       表单配置信息
     * @param flyQiuColumnInfo 列信息
     * @return List
     */
    private List<SqlColumnModel> createSQLTable(FlyQiuTableConfig formConfig, FlyQiuColumnInfo flyQiuColumnInfo) {
        List<SqlColumnModel> columns = new ArrayList<>();
        columns.addAll(flyQiuColumnInfo.getAddLists());
        columns.addAll(flyQiuColumnInfo.getEditColumns());
        storageMapper.createTable(formConfig, columns);
        synchronizeColumn(formConfig, columns);
        return columns;
    }

    private void synchronizeColumn(FlyQiuTableConfig formConfig, List<SqlColumnModel> columns) {
        List<SqlColumnModel> columnModels = getStorageColumnConfig(formConfig);
        Map<String, SqlColumnModel> columnModelMap = columnModels.stream().collect(Collectors.toMap(SqlColumnModel::getProp, e -> e));

        for (SqlColumnModel columnModel : columns) {
            String prop = columnModel.getProp();
            columnModel.setId(columnModel.getProp());
            if (!columnModelMap.containsKey(prop)) {
                continue;
            }
            SqlColumnModel model = columnModelMap.get(prop);
            columnModel.setSqlDataType(model.getSqlDataType());
            columnModel.setSqlDataLength(model.getSqlDataLength());
            columnModel.setPrecision(model.getPrecision());
        }

    }

    /**
     * 删除列
     *
     * @param tableName
     * @param deleteLists
     */
    private void deleteColumns(String tableName, List<SqlColumnModel> deleteLists) {
        if (deleteLists == null || deleteLists.isEmpty()) return;
        for (SqlColumnModel column : deleteLists) {
            if (column.getProp().equals(FlyQiuFormConstant.FormBaseColumns.COLUMN_PK_NAME)) continue;
            storageMapper.deleteColumn(tableName, column);
        }
    }

    private void updateColumns(String tableName, List<SqlColumnVo> editLists) {
        if (editLists == null || editLists.isEmpty()) return;
        for (SqlColumnVo column : editLists) {
            storageMapper.updateColumn(tableName, column);
        }
    }

    private void addColumns(String tableName, List<SqlColumnModel> addLists) {
        if (addLists == null || addLists.isEmpty()) return;
        for (SqlColumnModel column : addLists) {
            storageMapper.addColumn(tableName, column);

        }
    }


    @Override
    public void storageDeleteTable(FlyQiuTableConfig formConfig) {
        Map<String, String> table = storageMapper.getTableByTableName(formConfig.getTableName());
        if (FlyQiuCollectionTools.isEmpty(table)) {
            return;
        }
        storageMapper.deleteTable(formConfig.getTableName());
    }


    @Override
    public void clearData(FlyQiuTableConfig formConfig) {
        storageMapper.clearData(formConfig.getTableName());
    }

}
